package com.yznote.cloudesk.file.controller;

import com.yznote.cloudesk.common.Anno.CacheCtrol;
import com.yznote.cloudesk.common.Anno.CacheType;
import com.yznote.cloudesk.common.Anno.CollectLogs;
import com.yznote.cloudesk.common.Anno.Table;
import com.yznote.cloudesk.common.constants.ModuleConstant;
import com.yznote.cloudesk.common.constants.YCacheConstant;
import com.yznote.cloudesk.common.constants.YConstant;
import com.yznote.cloudesk.common.pojo.DeskFile;
import com.yznote.cloudesk.common.pojo.File;
import com.yznote.cloudesk.common.pojo.Result;
import com.yznote.cloudesk.common.pojo.User;
import com.yznote.cloudesk.common.oss.OssUtils;
import com.yznote.cloudesk.cache.yCache.YCache;
import com.yznote.cloudesk.file.mapper.FileMapper;
import com.yznote.cloudesk.file.server.FileServer;
import com.yznote.cloudesk.common.tokenShare.YTokenShare;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Date;
import java.util.List;

/**
 * @author : xiaozhoutongxue
 * @date : 2022/10/15 22:59
 */
@Slf4j
@RestController
@CrossOrigin
@Api(tags = "文件系统")
@CollectLogs(needParam = true,needResponse = false,moduleName = ModuleConstant.FILE_MODULE)
@RequestMapping("/file")
public class FileController {
    @Autowired
    FileServer fileServer;
    @Autowired
    YTokenShare yTokenShare;
    @Autowired
    YCache yCache;
    @Autowired
    OssUtils ossUtils;
    @Autowired
    FileMapper fileMapper;

    @ApiOperation("得到一个文件详细信息")
    @GetMapping("/getFile")
    public Result getFile(@RequestParam Long fileId) {
        File filemsg = fileMapper.getFilemsg(fileId);
        return Result.success(filemsg);
    }

    @ApiOperation("得到一个桌面")
    @GetMapping("/getDesk")
    @CacheCtrol(type = CacheType.SELECT,cacheModule = YCacheConstant.DESK,saveCache = false,
            value = {
            Table.Desk,Table.File
            })
    public Result getDesk() {
        Long userId = yTokenShare.get().getUserId();
        List<DeskFile> data = (List<DeskFile>) yCache.tryGet(YCacheConstant.DESK,"getDesk:"+userId);
        if (data != null) {
            return Result.success(data);
        }
        List<DeskFile> desk = fileServer.getDesk(userId);
        if (desk == null) {
            return Result.build(null, 500, YConstant.ERROR_DATAEXC);
        }
        yCache.put(YCacheConstant.DESK, "getDesk:"+userId, desk);
        return Result.success(desk);
    }

    @ApiOperation("得到一个子文件列表by fileId")
    @GetMapping("/getSonFile")
    public Result getSonFile(@RequestParam Long fileId) {
        User user = yTokenShare.get();
        List<File> sonFile = fileServer.getSonFile(fileId, user.getUserId());
        return Result.success(sonFile);
    }

    @ApiOperation("得到一个文件by fileFaId and fileName")
    @GetMapping("/getFileByFaIdAndFileName")
    public Result getFileByFaIdAndFileName(@RequestParam Long fileFaId, @RequestParam String fileName) {
        File fileByFaIdAndFileName = fileServer.getFileByFaIdAndFileName(fileFaId, fileName);
        return Result.success(fileByFaIdAndFileName);
    }

    @ApiOperation("在当前目录下创建一个目录（给x和y则为桌面文件,给不给fileName都可以）")
    @PostMapping("/insertFile")
    public Result insertFile(@RequestBody DeskFile deskFile) throws UnsupportedEncodingException {
        String msg = fileServer.insertFile(deskFile, false, null);
        if (msg == YConstant.SUCCESS) {
            return Result.success(deskFile);
        } else if (msg == YConstant.ERROR_FILENAMEREPEAT) {
            return Result.build(null, 501, msg);
        } else {
            return Result.build(null, 500, msg);
        }
    }

    @ApiOperation("在当前目录新建一个文本文件，此时文件内容为空（给x和y则为桌面文件,给不给fileName都可以）")
    @PostMapping("/insertTextFile")
    public Result insertTextFile(@RequestBody DeskFile deskFile, @RequestParam(required = false) String afterName) throws UnsupportedEncodingException {
        String msg = fileServer.insertFile(deskFile, "", afterName);
        if (msg == YConstant.SUCCESS) {
            return Result.success(deskFile);
        } else if (msg == YConstant.ERROR_FILENAMEREPEAT) {
            return Result.build(null, 501, msg);
        } else {
            return Result.build(null, 500, msg);
        }
    }

    @ApiOperation("移入MultipartFile文件（给x和y则为桌面文件 ）")
    @PostMapping("/insertMultipartFile")
    public Result insertTextFile(DeskFile deskFile, @RequestParam MultipartFile mtf) throws IOException {
        String msg = fileServer.insertFile(deskFile, mtf);
        if (msg == YConstant.SUCCESS) {
            return Result.success(deskFile);
        } else if (msg == YConstant.ERROR_FILENAMEREPEAT) {
            return Result.build(null, 501, msg);
        } else {
            return Result.build(null, 500, msg);
        }
    }


    @ApiOperation("名字重复时的操作:覆盖true、改名false")
    @PostMapping("/removeRepeat")
    public Result removeRepeat(
            Long oldFileId,
            DeskFile deskFile,
            @RequestParam(required = false) MultipartFile mtf,
            @RequestParam Boolean isCoverage,
            @RequestParam(required = false) String afterName) throws IOException {
        if (afterName == null) {
            afterName = "";
        }
        String msg = fileServer.removeRepeat(oldFileId, deskFile, mtf, isCoverage, afterName);

        if (msg == YConstant.SUCCESS) {
            return Result.success(deskFile);
        } else if (msg == YConstant.ERROR_FILENAMEREPEAT) {
            return Result.build(null, 501, msg);
        }
        return Result.build(null, 500, msg);

    }

    @ApiOperation("在桌面移动目录或文件的位置")
    @PostMapping("/moveDeskFile")
    @CacheCtrol(value = {Table.Desk},
            saveCache = false,
            cacheModule = YCacheConstant.DESK,
            type = CacheType.MODIFY)
    public Result moveDeskFile(@RequestBody DeskFile deskFile) {
        String s = fileServer.moveDeskFile(deskFile.getFileId(), deskFile.getX(), deskFile.getY());
        return Result.success(null);
    }

    @ApiOperation("交换桌面文件位置")
    @PostMapping("/swapDeskFile")
    public Result swapDeskFile(
            @RequestBody DeskFile deskFile1,
            @RequestParam Long deskFileId2,
            @RequestParam Integer x,
            @RequestParam Integer y
    ) {
        DeskFile deskFile2 = new DeskFile();
        deskFile2.setFileId(deskFileId2);
        deskFile2.setX(x);
        deskFile2.setY(y);
        fileServer.swapDeskFile(deskFile1, deskFile2);
        return Result.success(null);
    }

    @ApiOperation("更改目录或者文件信息 ")
    @PostMapping("/updateFile")
    public Result updateFile(@RequestBody File file) {
        String msg = fileServer.updateFile(file);
        if (msg == YConstant.SUCCESS) {
            return Result.success(null);
        } else if (msg == YConstant.ERROR_FILENAMEREPEAT) {
            return Result.build(null, 501, msg);
        }
        return Result.build(null, 500, msg);
    }

    @ApiOperation("更改目录或者文件名字 ")
    @PostMapping("/updateFileName")
    public Result updateFileName(@RequestBody File file) {
        String msg = fileServer.updateFileName(file);
        if (msg == YConstant.SUCCESS) {
            yCache.delayDelete(YCacheConstant.DESK,yTokenShare.get().getUserId().toString());
            return Result.success(null);
        }
        return Result.build(null, 500, msg);
    }

    @ApiOperation("从桌面移动到其他位置")
    @PostMapping("/deskFileToFile")
    public Result deskFileToFile(@RequestParam Long fileId, @RequestParam Long newFileFaId) {
        String msg = fileServer.deskFileToFile(fileId, newFileFaId);
        if (msg == YConstant.SUCCESS) {
            yCache.delayDelete(YCacheConstant.DESK,yTokenShare.get().getUserId().toString());
            return Result.success(null);
        } else if (msg == YConstant.ERROR_FILENAMEREPEAT) {
            return Result.build(null, 501, msg);
        }
        return Result.build(null, 500, msg);
    }

    @ApiOperation("把文件移到桌面")
    @PostMapping("/toDeskFile")
    public Result toDeskFile(@RequestParam Long fileId, @RequestParam Integer x, @RequestParam Integer y) {
        String msg = fileServer.toDeskFile(fileId, x, y);
        if (msg == YConstant.SUCCESS) {
            yCache.delayDelete(YCacheConstant.DESK,yTokenShare.get().getUserId().toString());
            return Result.success(null);
        } else if (msg == YConstant.ERROR_FILENAMEREPEAT) {
            return Result.build(null, 501, msg);
        }
        return Result.build(null, 500, msg);
    }

    @ApiOperation("下载文件")
    @GetMapping("/downloadFile")
    public ResponseEntity downloadFile(HttpServletResponse response, @RequestParam Long fileId) throws IOException {
        File filemsg = fileMapper.getFilemsg(fileId);
        if (!filemsg.getUserId().equals(yTokenShare.get().getUserId())) {
            return null;
        }
        String ossURL = filemsg.getFilePath();
        byte[] resp;
        resp = yCache.tryGetByteArray(YCacheConstant.FILE, ossURL);
        if (resp == null) {
            resp = ossUtils.getFileSourceByPath(ossURL);
        }
        yCache.putByteArray(YCacheConstant.FILE, ossURL, resp);
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Content-Disposition", "attachment; filename=" + filemsg.getFileName());
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");
            headers.add("Last-Modified", new Date().toString());
            headers.add("ETag", String.valueOf(System.currentTimeMillis()));
            return ResponseEntity
                    .ok()
                    .headers(headers)
                    .contentLength(resp.length)
                    .contentType(MediaType.parseMediaType("application/octet-stream"))
                    .body(resp);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("dfsId:{}下载文件失败，cause:{}", e);
        }
        return null;
    }

    @ApiOperation("一键整理桌面")
    @GetMapping("/sortDesk")
    @CacheCtrol(value = {
            Table.Desk
    },type = CacheType.MODIFY,saveCache = false,cacheModule = YCacheConstant.DESK
    )
    public Result sortDesk() {
        Boolean res = fileServer.sortDesk(yTokenShare.get().getUserId());
        if (res) {
            return Result.success(null);
        }
        return Result.fail("整理失败");
    }
}
